package cn.xzqwjw.taskmanager.service.impl;

import cn.xzqwjw.taskmanager.common.customEnum.ResponseCodeEnum;
import cn.xzqwjw.taskmanager.common.exception.CustomException;
import cn.xzqwjw.taskmanager.domain.pojo.SysPurview;
import cn.xzqwjw.taskmanager.domain.pojo.SysPurviewRoute;
import cn.xzqwjw.taskmanager.domain.vo.ResponseVo;
import cn.xzqwjw.taskmanager.repository.SysPurviewMapper;
import cn.xzqwjw.taskmanager.service.SysPurviewRouteService;
import cn.xzqwjw.taskmanager.service.SysPurviewService;
import cn.xzqwjw.taskmanager.utils.CommonUtil;
import cn.xzqwjw.taskmanager.utils.ConvertUtil;
import cn.xzqwjw.taskmanager.utils.JsonUtil;
import cn.xzqwjw.taskmanager.utils.MyMapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author rush
 */
@Service("SysPurviewService")
@Transactional(rollbackFor = Exception.class)
public class SysPurviewServiceImpl extends ServiceImpl<SysPurviewMapper, SysPurview>
    implements SysPurviewService {

  private final SysPurviewMapper purviewMapper;
  private final SysPurviewRouteService purviewRouteService;

  @Autowired
  public SysPurviewServiceImpl(SysPurviewMapper purviewMapper,
                               SysPurviewRouteService purviewRouteService) {
    this.purviewMapper = purviewMapper;
    this.purviewRouteService = purviewRouteService;
  }

  /**
   * 前端传值为 {"FrontRouteId":"1","SysPurview",{"id":1,...}}
   */
  @Override
  public String add(String paramsJson) {
    CommonUtil.checkNull(paramsJson);
    Map<?, ?> paramsMap = JsonUtil.json2Obj(paramsJson, Map.class);
    Integer idRoute = parseIdRoute(paramsMap);
    SysPurview sysPurview = parseSysPurview(paramsMap);
    // 添加权限
    if (!save(sysPurview)) {
      throw new CustomException(ResponseCodeEnum.ERROR_INSERT);
    }
    // 3、添加角色对应的所有权限
    if (addRouteIdByIdPurview(sysPurview.getId(), idRoute)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_CREATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_INSERT);
    }
  }

  @Override
  public String addBatch(List<SysPurview> list) {
    CommonUtil.checkNull(list);
    // 1、循环判断批量添加的权限是否已添加
    for (SysPurview purview : list) {
      if (validLabel(purview.getLabel()) || validCode(purview.getCode())) {
        throw new CustomException(ResponseCodeEnum.UNPROCESSABLE_ENTITY);
      }
    }
    // 2、批量添加权限以及权限并添加一条默认路由id为1的路由
    SysPurviewRoute purviewRoute;
    int i = 0;
    for (SysPurview purview : list) {
      if (save(purview)) {
        purviewRoute = new SysPurviewRoute();
        purviewRoute.setIdPurview(purview.getId());
        purviewRoute.setIdRoute(1);
        purviewRouteService.add(purviewRoute);
        i = i + 1;
      }
    }
    if (i == list.size()) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_CREATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_INSERT);
    }
  }

  @Override
  public String delById(Integer id) {
    CommonUtil.checkId(id);
    if (removeById(id)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_DELETED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_DELETE);
    }
  }

  @Override
  public String modifyAll(SysPurview purview) {
    CommonUtil.checkNull(purview);
    if (updateById(purview)) {
      return JsonUtil.obj2Json(ResponseVo.success(ResponseCodeEnum.OK_UPDATED));
    } else {
      throw new CustomException(ResponseCodeEnum.ERROR_UPDATE);
    }
  }

  @Override
  public String queryById(Integer id) {
    CommonUtil.checkId(id);
    SysPurview purview = getById(id);
    if (purview != null) {
      return JsonUtil.obj2Json(ResponseVo.success(purview));
    } else {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
  }

  /**
   * 根据权限id获取此权限所有信息，包括权限对应的路由和包括此权限的角色及相关的管理员
   */
  @Override
  public SysPurview getDetailById(Integer id) {
    return purviewMapper.getDetailById(id);
  }

  /**
   * 添加权限时要先看看权限中文名是否已经用过
   */
  @Override
  public String checkLabel(String label) {
    Map<String, Boolean> returnMap = new HashMap<>(16);
    returnMap.put("IsAdded", validLabel(label));
    return JsonUtil.obj2Json(ResponseVo.success(returnMap));
  }

  /**
   * 添加权限时要先看看权限英文代码是否已经用过
   */
  @Override
  public String checkCode(String code) {
    Map<String, Boolean> returnMap = new HashMap<>(16);
    returnMap.put("IsAdded", validCode(code));
    return JsonUtil.obj2Json(ResponseVo.success(returnMap));
  }

  /**
   * 根据自定义的 listAll 得到所有权限列表
   */
  @Override
  public String listAll() {
    List<SysPurview> resultList = purviewMapper.listAll();
    return JsonUtil.obj2Json(ResponseVo.success(resultList));
  }

  @Override
  public String listAllByTag() {
    String[] allTags = getTags();
    List<Map<String, Object>> purviewByTagList = new ArrayList<>();
    Map<String, Object> tempMap;
    for (String tag : allTags) {
      if (StringUtils.hasText(tag)) {
        tempMap = new HashMap<>(16);
        tempMap.put("Tag", tag);
        tempMap.put("PurviewList", listPurviewByTag(tag));
        purviewByTagList.add(tempMap);
      }
    }
    return JsonUtil.obj2Json(ResponseVo.success(purviewByTagList));
  }

  // ==================== 私有方法 ====================

  /**
   * 得到所有关键字
   */
  private String[] getTags() {
    QueryWrapper<SysPurview> wrapper = new QueryWrapper<>();
    wrapper.select("tag")
        .gt("id", 1)
        .groupBy("tag");
    List<Map<String, Object>> tagMapList = listMaps(wrapper);
    List<String> tagList = new ArrayList<>();
    for (Map<String, Object> map : tagMapList) {
      tagList.add(map.get("tag").toString());
    }
    return tagList.toArray(new String[0]);
  }

  /**
   * 返回类似{"id":1,"name":xxx,"checked":false}这样的数据
   * 用于添加角色时，所有权限按关键字分组
   */
  private List<Map<String, Object>> listPurviewByTag(String tag) {
    QueryWrapper<SysPurview> wrapper = new QueryWrapper<>();
    wrapper.select("id", "label")
        .gt("id", 1)
        .eq("tag", tag);
    List<Map<String, Object>> returnList = listMaps(wrapper);
    for (Map<String, Object> map : returnList) {
      map.put("checked", false);
    }
    return returnList;
  }

  private boolean validLabel(String label) {
    QueryWrapper<SysPurview> wrapper = new QueryWrapper<>();
    wrapper.select("id").eq("label", label);
    return CommonUtil.hasAdded(getMap(wrapper));
  }

  private boolean validCode(String code) {
    QueryWrapper<SysPurview> wrapper = new QueryWrapper<>();
    wrapper.select("id").eq("code", code);
    return CommonUtil.hasAdded(getMap(wrapper));
  }

  /**
   * 添加或修改某条权限对应的前端路由
   * 无论是添加还是修改都是先删除已有的再重新添加新的
   */
  private Boolean addRouteIdByIdPurview(Integer idPurview, Integer idRoute) {
    // 1、先把 idPurview 下的已有路由删除
    QueryWrapper<SysPurviewRoute> wrapper = new QueryWrapper<>();
    wrapper.eq("id_purview", idPurview)
        .gt("id", 0);
    purviewRouteService.remove(wrapper);
    // 2、向权限路由表里添加记录
    SysPurviewRoute purviewRoute = new SysPurviewRoute();
    purviewRoute.setIdPurview(idPurview);
    purviewRoute.setIdRoute(idRoute);
    return purviewRouteService.save(purviewRoute);
  }

  /**
   * 解析得到 SysPurview 对象
   */
  private SysPurview parseSysPurview(Map paramsMap) {
    try {
      return MyMapUtil.getValuePojo(paramsMap, "SysPurview", true, SysPurview.class);
    } catch (Exception e) {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
  }

  /**
   * 解析得到路由id
   */
  private Integer parseIdRoute(Map paramsMap) {
    Object obj = MyMapUtil.getValueObject(paramsMap, "FrontRouteId", true);
    if (obj instanceof Integer) {
      return ConvertUtil.obj2Int(obj);
    } else {
      throw new CustomException(ResponseCodeEnum.BAD_REQUEST);
    }
  }

}
